#ifndef _FXMATH_IMAGE_
#define _FXMATH_IMAGE_

//*****************************************************************************
//* Image-PDF Converter
//*****************************************************************************
/**
 * @name Image-PDF Converter
 */
/*@{*/

FX_DEFINEHANDLE(FX_HIMAGE);

class IFX_Image
{
public:
	virtual void				Release() = 0;

	virtual FX_HIMAGE			LoadImage(IFX_FileRead *pFileRead) = 0;
	virtual FXCODEC_IMAGE_TYPE	GetImageType(FX_HIMAGE hImage) const = 0;
	virtual void				EnableTransparentImage(FX_HIMAGE hImage, FX_BOOL bEnable) = 0;
	virtual void				SetBackgroundColor(FX_HIMAGE hImage, FX_ARGB argb) = 0;
	virtual void				SetImageOpacity(FX_HIMAGE hImage, FX_BYTE nOpacity) = 0;
	virtual FX_INT32			CountImageFrames(FX_HIMAGE hImage) const = 0;
	virtual FX_BOOL				LoadFrame(FX_HIMAGE hImage, FX_INT32 iFrame) = 0;
	virtual FX_BOOL				GetFrameSize(FX_HIMAGE hImage, FX_INT32 &width, FX_INT32 &height) const = 0;
	virtual CFX_DIBitmap*		GetFrameImage(FX_HIMAGE hImage) const = 0;
	virtual void				FreeImage(FX_HIMAGE hImage) = 0;
	virtual CFX_DIBAttribute*	GetImageAttribute(FX_HIMAGE hImage) const { return NULL; }

	virtual FX_INT32			GetWidth(FX_HIMAGE hImage) const = 0;
	virtual FX_INT32			GetHeight(FX_HIMAGE hImage) const = 0;
};

IFX_Image*			FX_Image_Create();

CPDF_ImageObject*	FX_CreateImageObject(CPDF_Document *pPDFDoc, FX_HIMAGE hImage, FX_INT32 nFrame, const CFX_Matrix *pMatrix = NULL);
CPDF_ImageObject*	FX_InsertImageToPDFPage(CPDF_PageObjects *pPDFPageObjects, FX_POSITION posInsert, FX_HIMAGE hImage, FX_INT32 nFrame, const CFX_Matrix &matrix);
FX_INT32			FX_InsertImageToPDFDocument(CPDF_Document *pPDFDoc, FX_INT32 iPageStart, FX_HIMAGE hImage, FX_INT32 iFrameStart = 0, FX_INT32 iFrameCount = -1);

/*@}*/

//*****************************************************************************
//* Grayscale bitmap
//*****************************************************************************
/**
 * @name	Grayscale bitmap
 * @note	Helper class to store grayscale bitmap. Its format is FXDIB_8bppRgb without palette.
 */
/*@{*/

class CFX_GrayscaleBitmap : public CFX_DIBitmap
{
public:
	CFX_GrayscaleBitmap(IFX_Allocator* pAllocator = NULL) : CFX_DIBitmap(), m_pAllocator(pAllocator) {}

	void		Release();

	FX_BOOL		Create(FX_INT32 width, FX_INT32 height);

protected:
	virtual ~CFX_GrayscaleBitmap();

	IFX_Allocator*	m_pAllocator;
};

/*@}*/

/**
 * @name	Grayscale
 * @note	Convert any DIB source object into grayscale bitmap.<br>
 *			At present, this class supports FXDIB_Rgb, FXDIB_Rgba, FXDIB_Rgb32, FXDIB_Argb, FXDIB_Cmyk, FXDIB_Cmyka.
 */
/*@{*/

class CFX_Grayscale
{
public:
	/** @brief	Constructor with allocator. */
	CFX_Grayscale(IFX_Allocator* pAllocator = NULL)
		: m_pAllocator(pAllocator)
		, m_pDIBSource(NULL)
		, m_pGSLine(NULL)
	{}
	/** @brief	Destructor. */
	~CFX_Grayscale() {UnloadDIBSource();}

	/**
	 * @brief	Load a DIB source to retrieve grayscale value.
	 *
	 * @praram[in] pDIBSource	Pointer to a ::CFX_DIBSource object.<br>
	 *							It should be valid and its format is limited to FXDIB_Rgb, FXDIB_Rgba, FXDIB_Rgb32, FXDIB_Argb, FXDIB_Cmyk, FXDIB_Cmyka at present.
	 *
	 * @return	TRUE if success, FALSE if cannot load specified DIB source.
	 */
	FX_BOOL					LoadDIBSource(CFX_DIBSource* pDIBSource);

	/**
	 * @brief	Unload the current DIB source.
	 *
	 * @return	None.
	 */
	void					UnloadDIBSource();

	/**
	 * @brief	Convert a given scan line to grayscale data.
	 *
	 * @praram[in] lineIndex	Scan line index. It starts from 0, and limits to the height of DIB source.
	 *
	 * @return	TRUE if success, FALSE if cannot convert.
	 */
	FX_BOOL					ConvertToGrayscaleLine(FX_INT32 lineIndex);

	/**
	 * @brief	Get the current grayscale data.
	 *
	 * @return	Buffer to the current grayscale data. It's a scan line converted by previous call to ::ConvertToGrayscaleLine. 
	 */
	FX_LPCBYTE				GetGrayscaleLine() const {return m_pGSLine;}

	/**
	 * @brief	Get a whole grayscale bitmap to DIB source.
	 *
	 * @return	A new DIB bitmap object which is a grayscale one, the format is FXDIB_8bppRgb without palette.<br>
	 *			Caller should call CFX_GrayscaleBitmap::Release to destroy the returned object.
	 */
	CFX_GrayscaleBitmap*	GetGrayscaleBitmap();

protected:
	IFX_Allocator*	m_pAllocator;
	CFX_DIBSource*	m_pDIBSource;
	FX_LPBYTE		m_pGSLine;
};

/*@}*/

/**
 * @brief	Calculate bitmap margin according to a given color or detect automatically.
 *
 * @param[in] pDIBBuffer	Pointer to DIB bitmap buffer.
 * @param[in] dibFormat		DIB format, refer to ::FXDIB_Format.
 * @param[in] width			Width of DIB bitmap.
 * @param[in] height		Height of DIB bitmap.
 * @param[in] stride		Stride or pitch of DIB bitmap.
 * @param[in] flag			Specifies the method to calculate margin, 0 means matching the given background color <i>backColor</i> exactly, 1 means detecting margin by analyzing bitmap.
 * @param[in] backColor		Background color, it's valid only when <i>flag</i> is 0. <i>backColor</i> has the same color format with <i>dibFormat</i>.
 * @param[in] windowSize	Detection size to analyze background, it's valid only when <i>flag</i> is 1.
 * @param[in] tolerance		Color difference when detect margin, it's valid only when <i>flag</i> is 1. Its value should be between 0 and 255, suggested value is 64.
 * @param[out] rtMargin		Margin rectangle returned.
 * @param[in] pAllocator	Pointer to a ::IFX_Allocator object which specifies an allocator.
 *
 * @return	TRUE if success, or FALSE if any error is found.
 */
FX_BOOL		FX_CalcBitmapMargin(FX_LPCBYTE pDIBBuffer, FXDIB_Format dibFormat, FX_INT32 width, FX_INT32 height, FX_INT32 stride, FX_INT32 flag, FX_DWORD backColor, FX_INT32 windowSize, FX_INT32 tolerance, CFX_Rect &rtMargin, IFX_Allocator* pAllocator = NULL);

/**
 * @brief	Calculate PDF page margin.
 *
 * @param[in] pPage			Pointer to ::CPDF_Page which is a PDF page.
 * @param[in] mode			Mode value specifies how to calculate page margin.<br>
 *							0 means calculating bounding box of all page contents;<br>
 *							1 means excepting all path objects if they like background;<br>
 *							2 means detecting the first image object and calculating image margin;<br>
 *							3 means detecting all path objects and images and calculating margin.
 * @param[in] pathPercent	Path percentage when a path object occupies page area, valid for mode 1 or 3.
 * @param[in] imagePercent	Image percentage when an image object occupies page area, valid for mode 2 or 3.
 * @param[in] windowSize	Detection size to analyze background, it's valid for mode 2 or 3 and used for image object.
 * @param[in] tolerance		Color difference when detect margin, it's valid for mode 2 or 3 and used for image object. Its value should be between 0 and 255, suggested value is 64.
 * @param[out] rtMargin		Margin rectangle returned.
 *
 * @return	TRUE if success, or FALSE if any error is found.
 */
FX_BOOL		FX_CalcPDFPageMargin(CPDF_Page* pPage, FX_INT32 mode, FX_INT32 pathPercent, FX_INT32 imagePercent, FX_INT32 windowSize, FX_INT32 tolerance, CPDF_Rect &rtMargin);

#endif //_FXMATH_IMAGE_
